use axum::{
    body::Body,
    extract::{Path, RawQuery},
    http::{header, HeaderMap, StatusCode},
    response::IntoResponse,
};
use futures_util::stream;
use shq_common::prelude::{
    get_home_visit_import_template, get_import_template, get_page_config, get_work_path,
    ExportQueryParams, ExportReptParams, OrderItems, WhereCauses,
};
use shq_pas_backend::PageService;
pub async fn export_xlsx_from_page(RawQuery(query): RawQuery) -> impl IntoResponse {
    let params: ExportQueryParams = serde_qs::from_str(query.unwrap().as_str()).unwrap();
    let wcs: Option<WhereCauses> = params
        .filters
        .map(|f| serde_json::from_str(f.as_str()).unwrap())
        .unwrap_or(None);
    let ois: Option<OrderItems> = params
        .orders
        .map(|o| serde_json::from_str(o.as_str()).unwrap())
        .unwrap_or(None);
    let ps = PageService::new(params.conf_name.as_str(), params.user_id, params.menu_id);
    let res = ps.export_excel(params.display_cols, wcs, ois).await;
    match res {
        Ok(datas) => {
            let chunks: Vec<std::io::Result<_>> = vec![Ok(datas)];
            let s = stream::iter(chunks);
            let body = Body::from_stream(s);
            let mut headers = HeaderMap::new();
            headers.insert(
                header::CONTENT_TYPE,
                "application/vnd.ms-excel".parse().unwrap(),
            );
            Ok((headers, body))
        }
        Err(err) => Err((StatusCode::BAD_REQUEST, err.to_string())),
    }
}
pub async fn export_rept_xlsx(RawQuery(query): RawQuery) -> impl IntoResponse {
    let qps: ExportReptParams = serde_qs::from_str(query.unwrap().as_str()).unwrap();
    let wcs: Option<WhereCauses> = qps
        .filters
        .map(|f| serde_json::from_str(f.as_str()).unwrap())
        .unwrap_or(None);
    let ois: Option<OrderItems> = qps
        .orders
        .map(|o| serde_json::from_str(o.as_str()).unwrap())
        .unwrap_or(None);
    let params = qps
        .params
        .iter()
        .map(|(k, v)| (k.as_str(), v.as_str()))
        .collect::<Vec<(&str, &str)>>();
    let one_sheet_on_file=qps.one_sheet_on_file;
    let conf = shq_report::get_rept_config(qps.rept_name.as_str());
    if conf.is_none() {
        return Err((
            StatusCode::BAD_REQUEST,
            format!("报表{}没有找到", qps.rept_name),
        ));
    }
    let conf = conf.unwrap();
    let kind = if one_sheet_on_file && conf.export_sheet_col_name.is_some() {
        "application/zip"
    } else {
        "application/vnd.ms-excel"
    };
    let rept_sevr =
        shq_report::ReportService::new(&qps.rept_name, &params, qps.user_id, qps.perm_id).await;
    match rept_sevr {
        Ok(rs) => {
            let res = rs
                .export_xslx(
                    wcs,
                    ois,
                    qps.display_cols,
                    qps.group_index,
                    qps.drill_down_requ,
                    qps.extra_where,
                    one_sheet_on_file
                )
                .await;
            match res {
                Ok(datas) => {
                    let chunks: Vec<std::io::Result<_>> = vec![Ok(datas)];
                    let s = stream::iter(chunks);
                    let body = Body::from_stream(s);
                    let mut headers = HeaderMap::new();
                    headers.insert(header::CONTENT_TYPE, kind.parse().unwrap());
                    Ok((headers, body))
                }
                Err(err) => Err((StatusCode::BAD_REQUEST, err.to_string())),
            }
        }
        Err(err) => Err((StatusCode::BAD_REQUEST, err.to_string())),
    }
}
pub async fn export_import_template(Path(conf_name): Path<String>) -> impl IntoResponse {
    let conf = get_page_config(conf_name.as_str())
        .or_else(|err| Err((StatusCode::BAD_REQUEST, err.to_string())))?;
    let imp_conf = conf
        .import_props
        .as_ref()
        .ok_or((StatusCode::BAD_REQUEST, "import_props没有配置".to_string()))?;
    let res = get_import_template(imp_conf, &conf.field_props);
    match res {
        Ok(datas) => {
            let chunks: Vec<std::io::Result<_>> = vec![Ok(datas)];
            let s = stream::iter(chunks);
            let body = Body::from_stream(s);
            let mut headers = HeaderMap::new();
            headers.insert(
                header::CONTENT_TYPE,
                "application/vnd.ms-excel".parse().unwrap(),
            );
            Ok((headers, body))
        }
        Err(err) => Err((StatusCode::BAD_REQUEST, err.to_string())),
    }
}
pub async fn export_import_home_visit_template(Path(uid): Path<u64>) -> impl IntoResponse {
    //文件目录
    // let file_name = String::from("员工家访情况记录表.xlsx");
    // let conf_path =
    //         std::env::var(work_path).unwrap_or("./template_files".to_string());
    let file_path = format!("{}/template_files/员工家访情况记录表.xlsx", get_work_path());

    //替换文件内容
    let res = get_home_visit_import_template(file_path, uid).await;

    match res {
        Ok(datas) => {
            let chunks: Vec<std::io::Result<_>> = vec![Ok(datas)];
            let s = stream::iter(chunks);
            let body = Body::from_stream(s);
            let mut headers = HeaderMap::new();
            headers.insert(
                header::CONTENT_TYPE,
                "application/vnd.ms-excel".parse().unwrap(),
            );
            Ok((headers, body))
        }
        Err(err) => Err((StatusCode::BAD_REQUEST, err.to_string())),
    }
}

pub async fn get_binary_file(Path(id): Path<u64>) -> impl IntoResponse {
    let file = shq_common::prelude::retrieve_binary_file(id).await;
    match file {
        Ok(file) => {
            let mut headers = HeaderMap::new();
            let ctype = format!("application/{}", file.file_type);
            headers.insert(header::CONTENT_TYPE, ctype.parse().unwrap());
            Ok((headers, Body::from(file.file_data)))
        }
        Err(err) => Err((StatusCode::NOT_FOUND, err.to_string())),
    }
}
